package log

import (
	"bytes"
	"fmt"
	"os"

	"gitee.com/doraemon1996/bunny/structure"
)

const (
	cacheMax = 64 * 1024 // 缓存大小限制 64K
)

// 日志数据异步处理对象
type writer struct {
	ctl *structure.Control

	// 日志对象
	logger *Logger

	// 跨协程日志数据传递通道
	pipe chan *bytes.Buffer
}

func (w *writer) Start() {
	w.ctl.Start(func() {
		w.ctl.Add(1)
		go w.loop()
	})
}

func (w *writer) Stop() {
	w.ctl.Stop(func() {
		w.ctl.Wait()
		close(w.pipe)
	})
}

func (w *writer) Append(buffer *bytes.Buffer) {
	if !w.ctl.Closed() {
		w.pipe <- buffer
	}
}

func (w *writer) loop() {
	defer w.ctl.Done()

	cache := bufPool.Get()
	defer bufPool.Put(cache)

	for {
		for len(w.pipe) > 0 {
			buffer := <-w.pipe
			if buffer.Len()+cache.Len() > cacheMax {
				if _, err := cache.WriteTo(w.logger.Output); err != nil {
					fmt.Fprintf(os.Stderr, "Failed to write to logger.Output. error: %v\n", err)
				}
				cache.Reset()
			}
			buffer.WriteTo(cache)
			buffer.Reset()
			bufPool.Put(buffer)
		}

		if cache.Len() > 0 {
			if _, err := cache.WriteTo(w.logger.Output); err != nil {
				fmt.Fprintf(os.Stderr, "Failed to write to logger.Output. error: %v\n", err)
			}
			cache.Reset()
		}

		if w.ctl.Closed() && len(w.pipe) == 0 {
			break
		}
	}
}
